
package bdz.projects.inl.core
{
	public class CoreVO implements ISerializable {
		
		protected var xmlValue:XML;
		protected var propList:Array;
		public var relations:Array;
		protected var relatedVO:Object;
		protected var linkPairs:Array;
		protected var propAttributes:Array;
		public var idField:String;
		public var extra:Object;
		
		public function CoreVO(defXML:XML = null, mvo:Object = null, dnode:String = null) {
			relatedVO = mvo;
			xmlValue = defXML || new XML("<"+dnode+"/>");
			if(defXML){
				deserialize(xmlValue);
			} 
			createPropertyAttributes();
		}
		protected function createCData(str:String, node:String):XML{
			return new XML("<"+node+"><![CDATA["+str+"]]></"+node+">");
		}
		protected function parseDataLinks(xlist:XMLList, ref:String, vo:Object):void{
			if(this[ref] == null){
				this[ref] = new Array();
			}
			for each(var xm:XML in xlist){
				this[ref].push(new vo(xm));
			}
		}
		protected function createPropertyAttributes():void{
			
		}
		protected function resetLinkPairs():void{
			for each(var obj:Object in linkPairs){
				this[obj.arr] = new Array();
			}
		}
		protected function updateXMLValue():void{
			
			for each(var prop:String in propList){
				if(xmlValue[prop] == null){
					xmlValue[prop] = new XML("<"+prop+"/>");
				} 
				if(this[prop]){
					if(this[prop] is Date){
						xmlValue[prop] = createCData(this[prop].getFullYear() + "-" + (this[prop].getMonth()) + "-" + this[prop].getDate(), prop); 	
					}else {
						xmlValue[prop] = createCData(this[prop].toString(), prop);
					}
				}else{
					if(prop != idField){
						xmlValue[prop] = createCData("", prop);
					}
				}
			}
			if(relations){
				
				if(relations.length == xmlValue.relationship.relation.length()){
					var cnt:Number = 0;
					for each(var cvo:CoreVO in relations){
						if(cvo){
							xmlValue.relationship.relation[cnt] = cvo.serialized;
							cnt++;
						}
					}
				}else if(relations.length){
					
					xmlValue.relationship = new XML("<relationship/>");
					xmlValue.relationship.relation = new XMLList();
					var cnt2:Number = 0;
					for each(var cvo2:CoreVO in relations){
						if(cvo2){
							xmlValue.relationship.relation[cnt2] = cvo2.serialized;
							cnt2++;
						}
					}
				}
			}
			if(linkPairs && linkPairs.length){
				handleUpdateLinkPairs();
			}
			
		}
		protected function handleDeserializeLinkPairs(xm:XML):void{
			for each(var obj:Object in linkPairs){
				try{
					if(xm[obj.tree][obj.node].length()){
						parseDataLinks(xm[obj.tree][obj.node], obj.arr, obj.vo);
					}
				}catch(e:Error){trace(e.message)}
			}
		}
		protected function handleUpdateLinkPairs():void{
			for each(var obj:Object in linkPairs){
				if(this[obj.arr]){
					if(this[obj.arr].length == xmlValue[obj.tree][obj.node].length()){
						var cnt:Number = 0;
						for each(var cvo:CoreVO in this[obj.arr]){
							if(cvo){
								xmlValue[obj.tree][obj.node][cnt] = cvo.serialized;
								cnt++;
							}
						}
					}else if(this[obj.arr].length){
						
						xmlValue[obj.tree] = new XML("<"+obj.tree+"/>");
						xmlValue[obj.tree][obj.node] = new XMLList();
						var cnt2:Number = 0;
						for each(var cvo2:CoreVO in this[obj.arr]){
							if(cvo2){
								xmlValue[obj.tree][obj.node][cnt2] = cvo2.serialized;
								cnt2++;
							}
						}
					}
				}
			}
		}
		protected function deserialize(xm:XML):void{
			resetLinkPairs();
			for each(var prop:String in propList){
				applyPropValue(prop, xm[prop].toString());
			}
			if(xm.relationship.relation.length() && relatedVO){
				parseMediaLink(xm.relationship.relation);
			}
			if(linkPairs && linkPairs.length){
				handleDeserializeLinkPairs(xm);
			}
				
		}
		protected function parseMediaLink(xlist:XMLList):void{
			relations = new Array();
			for each(var xm:XML in xlist){
				relations.push(new relatedVO(xm));
			}
		}
		protected function applyPropValue(prop:String, val:String):void{
			if(prop.indexOf("date") != -1){
				this[prop] = new Date(val.split("-")[0], val.split("-")[1], val.split("-")[2]);
			}else{
				this[prop] = val;
			}
		}
		public function removeFromRelatedArrayVO(propid:String, value:String, arr:String):void{
			var cnt:Number = 0;
			for each(var cvo:CoreVO in this[arr]){
				if(cvo[propid] == value){
					(this[arr] as Array).splice(cnt, 1);
					break;
				}
				cnt++;
			}
		}
		public function addToRelatedArrayVO(cvo:CoreVO, arr:String):void{
			if(this[arr] == null){
				this[arr] = new Array();
			}
			this[arr].push(cvo);
		}
		public function addRelatedVO(cvo:CoreVO):void{
			if(relations == null){
				relations = new Array();
			}
			relations.push(cvo);
		}
		public function get serialized():XML {
			updateXMLValue();
			return xmlValue;
		}
		
		public function set serialized(xm:XML):void	{
			deserialize(xm);
		}
		public function get propertyAttributes():Array{
			return propAttributes;
		}
		
	}
}
